/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "gtest/gtest.h"

#include "native_avcodec_base.h"
#include "native_avdemuxer.h"
#include "native_avformat.h"
#include "native_avsource.h"
#include "native_avmemory.h"

#include <iostream>
#include <cstdio>
#include <string>
#include <fcntl.h>
#include <sys/stat.h>

namespace OHOS {
namespace Media {
class DemuxerAlacFuncNdkTest : public testing::Test {
public:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp(void);
    void TearDown(void);

protected:
    const char* ALAC_M4A_1 = "/data/test/media/ALAC_16bit_44100Hz.m4a";
    const char* ALAC_M4A_2 = "/data/test/media/ALAC_24bit_48000Hz.m4a";
    const char* ALAC_M4A_3 = "/data/test/media/ALAC_32bit_96000Hz.m4a";
    
    const char* ALAC_MP4_1 = "/data/test/media/ALAC_16bit_44100Hz_mp4.mp4";
    const char* ALAC_MP4_2 = "/data/test/media/ALAC_24bit_48000Hz_mp4.mp4";
    const char* ALAC_MP4_3 = "/data/test/media/ALAC_32bit_96000Hz_mp4.mp4";
    
    const char* ALAC_MKV_1 = "/data/test/media/ALAC_16bit_44100Hz_mkv.mkv";
    const char* ALAC_MKV_2 = "/data/test/media/ALAC_24bit_48000Hz_mkv.mkv";
    const char* ALAC_MKV_3 = "/data/test/media/ALAC_32bit_96000Hz_mkv.mkv";
    
    const char* ALAC_MOV_1 = "/data/test/media/ALAC_16bit_44100Hz_mov.mov";
    const char* ALAC_MOV_2 = "/data/test/media/ALAC_24bit_48000Hz_mov.mov";
    const char* ALAC_MOV_3 = "/data/test/media/ALAC_32bit_96000Hz_mov.mov";
};

static OH_AVMemory* memory = nullptr;
static OH_AVSource* source = nullptr;
static OH_AVDemuxer* demuxer = nullptr;
static OH_AVFormat* sourceFormat = nullptr;
static OH_AVFormat* trackFormat = nullptr;
static OH_AVBuffer* avBuffer = nullptr;
static OH_AVFormat* format = nullptr;
static int32_t g_trackCount;
static int32_t g_memorySize = 1024 * 1024;
constexpr int32_t THOUSAND = 1000;
constexpr int32_t DEFAULT_TRACK_COUNT = 1;

void DemuxerAlacFuncNdkTest::SetUpTestCase() {}
void DemuxerAlacFuncNdkTest::TearDownTestCase() {}

void DemuxerAlacFuncNdkTest::SetUp()
{
    memory = OH_AVMemory_Create(g_memorySize);
    g_trackCount = 0;
}

void DemuxerAlacFuncNdkTest::TearDown()
{
    if (trackFormat != nullptr) {
        OH_AVFormat_Destroy(trackFormat);
        trackFormat = nullptr;
    }
    if (sourceFormat != nullptr) {
        OH_AVFormat_Destroy(sourceFormat);
        sourceFormat = nullptr;
    }
    if (format != nullptr) {
        OH_AVFormat_Destroy(format);
        format = nullptr;
    }
    if (memory != nullptr) {
        OH_AVMemory_Destroy(memory);
        memory = nullptr;
    }
    if (source != nullptr) {
        OH_AVSource_Destroy(source);
        source = nullptr;
    }
    if (demuxer != nullptr) {
        OH_AVDemuxer_Destroy(demuxer);
        demuxer = nullptr;
    }
    if (avBuffer != nullptr) {
        OH_AVBuffer_Destroy(avBuffer);
        avBuffer = nullptr;
    }
}
} // namespace Media
} // namespace OHOS

using namespace std;
using namespace OHOS;
using namespace OHOS::Media;
using namespace testing::ext;

static int64_t GetFileSize(const char* fileName)
{
    int64_t fileSize = 0;
    if (fileName != nullptr) {
        struct stat fileStatus {};
        if (stat(fileName, &fileStatus) == 0) {
            fileSize = static_cast<int64_t>(fileStatus.st_size);
        }
    }
    return fileSize;
}

struct seekInfo {
    const char* fileName;
    OH_AVSeekMode seekmode;
    int64_t millisecond;
    int32_t audioCount;
};

static void CheckSeekMode(seekInfo seekInfo)
{
    int trackType = 0;
    OH_AVCodecBufferAttr attr;
    int fd = open(seekInfo.fileName, O_RDONLY);
    int64_t size = GetFileSize(seekInfo.fileName);
    cout << seekInfo.fileName << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_NE(sourceFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    cout << "track count: " << g_trackCount << endl;
    
    for (int32_t index = 0; index < g_trackCount; index++) {
        ASSERT_EQ(AV_ERR_OK, OH_AVDemuxer_SelectTrackByID(demuxer, index));
    }
    
    for (int32_t index = 0; index < g_trackCount; index++) {
        trackFormat = OH_AVSource_GetTrackFormat(source, index);
        ASSERT_NE(trackFormat, nullptr);
        ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
        
        ASSERT_EQ(AV_ERR_OK, OH_AVDemuxer_SeekToTime(
            demuxer, seekInfo.millisecond / THOUSAND, seekInfo.seekmode));
        
        bool readEnd = false;
        int32_t frameNum = 0;
        while (!readEnd) {
            ASSERT_EQ(AV_ERR_OK, OH_AVDemuxer_ReadSample(demuxer, index, memory, &attr));
            if (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
                readEnd = true;
                break;
            }
            frameNum++;
        }
        
        if (trackType == MEDIA_TYPE_AUD) {
            cout << "audio frame count after seek: " << frameNum << endl;
            ASSERT_EQ(seekInfo.audioCount, frameNum);
        }
    }
    close(fd);
}

static void DemuxerAlacResult(const char* fileName, int32_t expectedFrames, int32_t expectedKeyFrames)
{
    int trackType = 0;
    OH_AVCodecBufferAttr attr;
    bool isEnd = false;
    int32_t frameCount = 0;
    int32_t keyFrameCount = 0;
    
    int fd = open(fileName, O_RDONLY);
    int64_t size = GetFileSize(fileName);
    cout << fileName << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    ASSERT_EQ(g_trackCount, DEFAULT_TRACK_COUNT);
    
    for (int32_t index = 0; index < g_trackCount; index++) {
        ASSERT_EQ(AV_ERR_OK, OH_AVDemuxer_SelectTrackByID(demuxer, index));
        trackFormat = OH_AVSource_GetTrackFormat(source, index);
        ASSERT_NE(trackFormat, nullptr);
        ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
        ASSERT_EQ(trackType, MEDIA_TYPE_AUD);
        
        while (!isEnd) {
            ASSERT_EQ(AV_ERR_OK, OH_AVDemuxer_ReadSample(demuxer, index, memory, &attr));
            if (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
                isEnd = true;
                break;
            }
            frameCount++;
            if (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_SYNC_FRAME) {
                keyFrameCount++;
            }
        }
    }
    
    ASSERT_EQ(frameCount, expectedFrames);
    ASSERT_EQ(keyFrameCount, expectedKeyFrames);
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0001
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_BITS_PER_CODED_SAMPLE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0001, TestSize.Level2) {
    int32_t bitDepth = 0;
    const char* file = ALAC_M4A_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_BITS_PER_CODED_SAMPLE, &bitDepth));
    ASSERT_EQ(bitDepth, 16);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0002
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_AUD_SAMPLE_RATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0002, TestSize.Level2) {
    int32_t sampleRate = 0;
    const char* file = ALAC_M4A_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate));
    ASSERT_EQ(sampleRate, 48000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0003
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_AUD_CHANNEL_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0003, TestSize.Level2) {
    int32_t channelCount = 0;
    const char* file = ALAC_M4A_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount));
    ASSERT_EQ(channelCount, 6);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0004
 * @tc.name      : demuxer ALAC ,GetSourceFormat,OH_MD_KEY_TRACK_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0004, TestSize.Level2) {
    const char* file = ALAC_M4A_3;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    ASSERT_EQ(g_trackCount, DEFAULT_TRACK_COUNT);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0005
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_TRACK_TYPE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0005, TestSize.Level2) {
    int32_t trackType = 0;
    const char* file = ALAC_M4A_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
    ASSERT_EQ(trackType, MEDIA_TYPE_AUD);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0006
 * @tc.name      : demuxer ALAC ,ReadSample,check sample size
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0006, TestSize.Level2) {
    OH_AVCodecBufferAttr attr{};
    const char* file = ALAC_M4A_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    ASSERT_EQ(OH_AVDemuxer_SelectTrackByID(demuxer, 0), AV_ERR_OK);
    
    ASSERT_EQ(OH_AVDemuxer_ReadSample(demuxer, 0, memory, &attr), AV_ERR_OK);
    ASSERT_GT(attr.size, 0);
    ASSERT_EQ(attr.pts, 0);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0007
 * @tc.name      : demuxer ALAC ,full demux,16bit stereo
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0007, TestSize.Level2) {
    DemuxerAlacResult(ALAC_M4A_1, 54, 54);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0008
 * @tc.name      : demuxer ALAC ,full demux,24bit 5.1
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0008, TestSize.Level2) {
    DemuxerAlacResult(ALAC_M4A_2, 79, 79);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0009
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_BITRATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0009, TestSize.Level2) {
    int64_t bitRate = 0;
    const char* file = ALAC_M4A_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_BITRATE, &bitRate));
    ASSERT_GT(bitRate, 0);
    ASSERT_LT(bitRate, 2000000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0010
 * @tc.name      : demuxer ALAC ,GetTrackFormat,OH_MD_KEY_CHANNEL_LAYOUT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0010, TestSize.Level2) {
    int64_t channelLayout = 0;
    const char* file = ALAC_M4A_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_CHANNEL_LAYOUT, &channelLayout));
    ASSERT_EQ(channelLayout, 0x3F);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0011
 * @tc.name      : demuxer ALAC(MP4) ,GetTrackFormat,OH_MD_KEY_BITS_PER_CODED_SAMPLE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0011, TestSize.Level2) {
    int32_t bitDepth = 0;
    const char* file = ALAC_MP4_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_BITS_PER_CODED_SAMPLE, &bitDepth));
    ASSERT_EQ(bitDepth, 16);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0012
 * @tc.name      : demuxer ALAC(MP4) ,GetTrackFormat,OH_MD_KEY_AUD_SAMPLE_RATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0012, TestSize.Level2) {
    int32_t sampleRate = 0;
    const char* file = ALAC_MP4_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate));
    ASSERT_EQ(sampleRate, 48000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0013
 * @tc.name      : demuxer ALAC(MP4) ,GetTrackFormat,OH_MD_KEY_AUD_CHANNEL_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0013, TestSize.Level2) {
    int32_t channelCount = 0;
    const char* file = ALAC_MP4_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount));
    ASSERT_EQ(channelCount, 6);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0014
 * @tc.name      : demuxer ALAC(MP4) ,GetSourceFormat,OH_MD_KEY_TRACK_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0014, TestSize.Level2) {
    const char* file = ALAC_MP4_3;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    ASSERT_EQ(g_trackCount, DEFAULT_TRACK_COUNT);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0015
 * @tc.name      : demuxer ALAC(MP4) ,GetTrackFormat,OH_MD_KEY_TRACK_TYPE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0015, TestSize.Level2) {
    int32_t trackType = 0;
    const char* file = ALAC_MP4_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
    ASSERT_EQ(trackType, MEDIA_TYPE_AUD);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0016
 * @tc.name      : demuxer ALAC(MP4) ,ReadSample,check sample size
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0016, TestSize.Level2) {
    OH_AVCodecBufferAttr attr{};
    const char* file = ALAC_MP4_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    ASSERT_EQ(OH_AVDemuxer_SelectTrackByID(demuxer, 0), AV_ERR_OK);
    
    ASSERT_EQ(OH_AVDemuxer_ReadSample(demuxer, 0, memory, &attr), AV_ERR_OK);
    ASSERT_GT(attr.size, 0);
    ASSERT_EQ(attr.pts, 0);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0017
 * @tc.name      : demuxer ALAC(MP4) ,full demux,16bit stereo
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0017, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MP4_1, 54, 54);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0018
 * @tc.name      : demuxer ALAC(MP4) ,full demux,24bit 5.1
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0018, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MP4_2, 79, 79);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0019
 * @tc.name      : demuxer ALAC(MP4) ,GetTrackFormat,OH_MD_KEY_BITRATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0019, TestSize.Level2) {
    int64_t bitRate = 0;
    const char* file = ALAC_MP4_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_BITRATE, &bitRate));
    ASSERT_GT(bitRate, 0);
    ASSERT_LT(bitRate, 2000000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0020
 * @tc.name      : demuxer ALAC(MP4) ,seek to middle,SEEK_MODE_NEXT_SYNC
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0020, TestSize.Level2) {
    seekInfo testInfo{ALAC_MP4_1, SEEK_MODE_NEXT_SYNC, 5000, 53};
    CheckSeekMode(testInfo);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0021
 * @tc.name      : demuxer ALAC(MKV) ,GetTrackFormat,OH_MD_KEY_BITS_PER_CODED_SAMPLE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0021, TestSize.Level2) {
    int32_t bitDepth = 0;
    const char* file = ALAC_MKV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_BITS_PER_CODED_SAMPLE, &bitDepth));
    ASSERT_EQ(bitDepth, 16);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0022
 * @tc.name      : demuxer ALAC(MKV) ,GetTrackFormat,OH_MD_KEY_AUD_SAMPLE_RATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0022, TestSize.Level2) {
    int32_t sampleRate = 0;
    const char* file = ALAC_MKV_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate));
    ASSERT_EQ(sampleRate, 48000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0023
 * @tc.name      : demuxer ALAC(MKV) ,GetTrackFormat,OH_MD_KEY_AUD_CHANNEL_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0023, TestSize.Level2) {
    int32_t channelCount = 0;
    const char* file = ALAC_MKV_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount));
    ASSERT_EQ(channelCount, 6);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0024
 * @tc.name      : demuxer ALAC(MKV) ,GetSourceFormat,OH_MD_KEY_TRACK_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0024, TestSize.Level2) {
    const char* file = ALAC_MKV_3;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    ASSERT_EQ(g_trackCount, DEFAULT_TRACK_COUNT);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0025
 * @tc.name      : demuxer ALAC(MKV) ,GetTrackFormat,OH_MD_KEY_TRACK_TYPE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0025, TestSize.Level2) {
    int32_t trackType = 0;
    const char* file = ALAC_MKV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
    ASSERT_EQ(trackType, MEDIA_TYPE_AUD);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0026
 * @tc.name      : demuxer ALAC(MKV) ,ReadSample,check sample size
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0026, TestSize.Level2) {
    OH_AVCodecBufferAttr attr{};
    const char* file = ALAC_MKV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    ASSERT_EQ(OH_AVDemuxer_SelectTrackByID(demuxer, 0), AV_ERR_OK);
    
    ASSERT_EQ(OH_AVDemuxer_ReadSample(demuxer, 0, memory, &attr), AV_ERR_OK);
    ASSERT_GT(attr.size, 0);
    ASSERT_EQ(attr.pts, 0);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0027
 * @tc.name      : demuxer ALAC(MKV) ,full demux,16bit stereo
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0027, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MKV_1, 54, 54);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0028
 * @tc.name      : demuxer ALAC(MKV) ,full demux,24bit 5.1
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0028, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MKV_2, 79, 79);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0029
 * @tc.name      : demuxer ALAC(MKV) ,GetTrackFormat,OH_MD_KEY_BITRATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0029, TestSize.Level2) {
    int64_t bitRate = 0;
    const char* file = ALAC_MKV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_FALSE(OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_BITRATE, &bitRate));
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0030
 * @tc.name      : demuxer ALAC(MKV) ,seek to near end,SEEK_MODE_CLOSEST_SYNC
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0030, TestSize.Level2) {
    seekInfo testInfo{ALAC_MKV_2, SEEK_MODE_CLOSEST_SYNC, 9000, 79};
    CheckSeekMode(testInfo);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0031
 * @tc.name      : demuxer ALAC(MOV) ,GetTrackFormat,OH_MD_KEY_BITS_PER_CODED_SAMPLE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0031, TestSize.Level2) {
    int32_t bitDepth = 0;
    const char* file = ALAC_MOV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_BITS_PER_CODED_SAMPLE, &bitDepth));
    ASSERT_EQ(bitDepth, 16);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0032
 * @tc.name      : demuxer ALAC(MOV) ,GetTrackFormat,OH_MD_KEY_AUD_SAMPLE_RATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0032, TestSize.Level2) {
    int32_t sampleRate = 0;
    const char* file = ALAC_MOV_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate));
    ASSERT_EQ(sampleRate, 48000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0033
 * @tc.name      : demuxer ALAC(MOV) ,GetTrackFormat,OH_MD_KEY_AUD_CHANNEL_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0033, TestSize.Level2) {
    int32_t channelCount = 0;
    const char* file = ALAC_MOV_2;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount));
    ASSERT_EQ(channelCount, 6);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0034
 * @tc.name      : demuxer ALAC(MOV) ,GetSourceFormat,OH_MD_KEY_TRACK_COUNT
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0034, TestSize.Level2) {
    const char* file = ALAC_MOV_3;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    sourceFormat = OH_AVSource_GetSourceFormat(source);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &g_trackCount));
    ASSERT_EQ(g_trackCount, DEFAULT_TRACK_COUNT);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0035
 * @tc.name      : demuxer ALAC(MOV) ,GetTrackFormat,OH_MD_KEY_TRACK_TYPE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0035, TestSize.Level2) {
    int32_t trackType = 0;
    const char* file = ALAC_MOV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType));
    ASSERT_EQ(trackType, MEDIA_TYPE_AUD);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0036
 * @tc.name      : demuxer ALAC(MOV) ,ReadSample,check sample size
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0036, TestSize.Level2) {
    OH_AVCodecBufferAttr attr{};
    const char* file = ALAC_MOV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    demuxer = OH_AVDemuxer_CreateWithSource(source);
    ASSERT_NE(demuxer, nullptr);
    ASSERT_EQ(OH_AVDemuxer_SelectTrackByID(demuxer, 0), AV_ERR_OK);
    
    ASSERT_EQ(OH_AVDemuxer_ReadSample(demuxer, 0, memory, &attr), AV_ERR_OK);
    ASSERT_GT(attr.size, 0);
    ASSERT_EQ(attr.pts, 0);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0037
 * @tc.name      : demuxer ALAC(MOV) ,full demux,16bit stereo
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0037, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MOV_1, 54, 54);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0038
 * @tc.name      : demuxer ALAC(MOV) ,full demux,24bit 5.1
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0038, TestSize.Level2) {
    DemuxerAlacResult(ALAC_MOV_2, 79, 79);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0039
 * @tc.name      : demuxer ALAC(MOV) ,GetTrackFormat,OH_MD_KEY_BITRATE
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0039, TestSize.Level2) {
    int64_t bitRate = 0;
    const char* file = ALAC_MOV_1;
    int fd = open(file, O_RDONLY);
    int64_t size = GetFileSize(file);
    cout << file << "-------fd:" << fd << "-------size:" << size << endl;
    
    source = OH_AVSource_CreateWithFD(fd, 0, size);
    ASSERT_NE(source, nullptr);
    
    trackFormat = OH_AVSource_GetTrackFormat(source, 0);
    ASSERT_NE(trackFormat, nullptr);
    ASSERT_TRUE(OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_BITRATE, &bitRate));
    ASSERT_GT(bitRate, 0);
    ASSERT_LT(bitRate, 2000000);
    
    close(fd);
}

/**
 * @tc.number    : DEMUXER_ALAC_FUNC_0040
 * @tc.name      : demuxer ALAC(MOV) ,seek to start,SEEK_MODE_PREVIOUS_SYNC
 * @tc.desc      : function test
 */
HWTEST_F(DemuxerAlacFuncNdkTest, DEMUXER_ALAC_FUNC_0040, TestSize.Level2) {
    seekInfo testInfo{ALAC_MOV_1, SEEK_MODE_PREVIOUS_SYNC, 0, 54};
    CheckSeekMode(testInfo);
}